import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.io.*;
import java.net.*;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class SrGachaUrl {

    void extractUrl(){
        String gamePath = "";
        System.out.println("尝试提取星铁抽卡链接");

        String appData = System.getenv("APPDATA");
        String localLowPath = Paths.get(appData, "..", "LocalLow", "miHoYo", "崩坏：星穹铁道").toString();
        String logPath = Paths.get(localLowPath, "Player.log").toString();

        if (!Files.exists(Paths.get(logPath))) {
            System.out.println("定位日志目录失败1!");
            return;
        }

        // Read the first 11 lines of the log file
        List<String> logLines;
        try {
            logLines = Files.readAllLines(Paths.get(logPath)).subList(0, 11);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("读取日志失败1");
            return;
        }

        if (logLines.isEmpty()) {
            logPath = Paths.get(localLowPath, "Player-prev.log").toString();
            if (!Files.exists(Paths.get(logPath))) {
                System.out.println("定位日志目录失败2!");
                return;
            }

            // Read the first 11 lines of the previous log file
            try {
                logLines = Files.readAllLines(Paths.get(logPath)).subList(0, 11);
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("读取日志失败2");
                return;
            }
        }

        if (logLines.isEmpty()) {
            System.out.println("无法通过日志定位游戏路径1");
            return;
        }

        for (String logLine : logLines) {
            if (logLine.startsWith("Loading player data from ")) {
                gamePath = logLine.replace("Loading player data from ", "").replace("data.unity3d", "");
                break;
            }
        }

        if (gamePath.isEmpty()) {
            System.out.println("无法通过日志定位游戏路径2");
            return;
        }

        String copyPath = "copyfile";
        String cachePath = Paths.get(gamePath, "webCaches", "Cache", "Cache_Data", "data_2").toString();
        File[] cacheFolders = new File(Paths.get(gamePath, "webCaches").toString()).listFiles(File::isDirectory);
        int maxVersion = 0;

        if (cacheFolders != null) {
            for (File cacheFolder : cacheFolders) {
                String folderName = cacheFolder.getName();
                Matcher matcher = Pattern.compile("^\\d+\\.\\d+\\.\\d+\\.\\d+$").matcher(folderName);
                if (matcher.matches()) {
                    int version = Arrays.stream(folderName.split("\\.")).mapToInt(Integer::parseInt).reduce(0, (a, b) -> a * 100 + b);
                    if (version >= maxVersion) {
                        maxVersion = version;
                        cachePath = Paths.get(gamePath, "webCaches", folderName, "Cache", "Cache_Data", "data_2").toString();
                    }
                }
            }
        }

        try {
            Path tempFile = Paths.get(copyPath);
            Files.copy(Paths.get(cachePath), tempFile, StandardCopyOption.REPLACE_EXISTING);
            String cacheData = new String(Files.readAllBytes(tempFile), StandardCharsets.UTF_8);
            Files.delete(tempFile);

            String[] cacheDataSplit = cacheData.split("1/0/");
            for (int i = cacheDataSplit.length - 1; i >= 0; i--) {
                String line = cacheDataSplit[i];

                if (line.startsWith("http") && line.contains("getGachaLog")) {
                    URI uri = new URI(line.split("\0")[0]);
                    // 这是原始抽卡链接
                    // System.out.println("--------[%s]".formatted(uri.toString()));

                    HttpClient client = HttpClient.newHttpClient();
                    HttpRequest request = HttpRequest.newBuilder(uri).header("Content-Type", "application/json").build();
                    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                    if (response.statusCode() == 200 && !response.body().contains("authkey")) {
                        Map<String, String> queryParams = parseQuery(uri.getQuery());
                        // Retain required params
                        queryParams.keySet().removeIf(key ->!(
                                key.equals("authkey") || key.equals("authkey_ver") ||
                                        key.equals("sign_type") || key.equals("game_biz") || key.equals("lang")));
                        String latestUrl = uri.getScheme() + "://" + uri.getHost() + uri.getRawPath() + "?" + buildQueryString(queryParams);
                        System.out.println("星铁抽卡链接提取成功(已复制到粘贴板，如果有权限的话)");
                        System.out.println(latestUrl);
                        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(latestUrl), null);
                        return;
                    }
                }
            }
            System.out.println("未找到有效抽卡链接，请尝试打开游戏抽卡记录窗口后过一会儿再试");
        } catch (IOException | InterruptedException | URISyntaxException e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }finally {
            Console console = System.console();
            if(Objects.nonNull(console)){
                console.readLine("按回车键退出");
            }
        }
    }

    boolean validate(String url)  {
        try {
            // 访问URL 拿到内容
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);
            connection.connect();
            if (connection.getResponseCode() != 200) {
                System.out.println("访问失败");
                return false;
            }
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line = reader.readLine();
            System.out.println(line);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return false;
    }


    private static Map<String, String> parseQuery(String query) {
        Map<String, String> queryParams = new LinkedHashMap<>();
        if (query != null) {
            String[] pairs = query.split("&");
            for (String pair : pairs) {
                String[] keyValue = pair.split("=",2);
                if (keyValue.length == 2) {
                    queryParams.put(keyValue[0], keyValue[1]);
                }
            }
        }
        return queryParams;
    }

    private static String buildQueryString(Map<String, String> queryParams) {
        return queryParams.entrySet().stream()
                .map(entry -> entry.getKey() + "=" + URLEncoder.encode(entry.getValue(),StandardCharsets.UTF_8))
                // .map(entry -> entry.getKey() + "=" + entry.getValue())
                .collect(Collectors.joining("&"));
    }
}
